/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.trello.rxlifecycle4.harmony.lifecycle;

import ohos.aafwk.ability.Lifecycle;

import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.functions.Function;

import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.OutsideLifecycleException;
import com.trello.rxlifecycle4.rxlifecycle_annotation.CheckResult;
import com.trello.rxlifecycle4.rxlifecycle_annotation.NonNull;

import static com.trello.rxlifecycle4.RxLifecycle.bind;

/**
 * For binding given source to harmony lifecycle.
 */
public final class RxLifecycleHarmonyLifecycle {
    private static final Function<Lifecycle.Event, Lifecycle.Event> LIFECYCLE = new Function<Lifecycle.Event,
            Lifecycle.Event>() {
        @Override
        public Lifecycle.Event apply(Lifecycle.Event lastEvent) throws Exception {
            switch (lastEvent) {
                case ON_START:
                    return Lifecycle.Event.ON_STOP;
                case ON_ACTIVE:
                    return Lifecycle.Event.ON_INACTIVE;
                case ON_FOREGROUND:
                    return Lifecycle.Event.ON_BACKGROUND;
                case ON_INACTIVE:
                    return Lifecycle.Event.ON_STOP;
                case ON_BACKGROUND:
                    return Lifecycle.Event.ON_STOP;
                case ON_STOP:
                    throw new OutsideLifecycleException("Cannot bind to Ability lifecycle when outside of it.");
                default:
                    throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
            }
        }
    };

    private RxLifecycleHarmonyLifecycle() {
        throw new AssertionError("No instances");
    }

    /**
     * Binds the given source to an Harmony lifecycle.
     * <p>
     * This helper automatically determines (based on the lifecycle sequence itself) when the source
     * should stop emitting items. In the case that the lifecycle sequence is in the
     * creation phase (ON_START, ON_ACTIVE, etc) it will choose the equivalent destructive phase (ON_STOP,
     * ON_INACTIVE, etc). If used in the destructive phase, the notifications will cease at the next event;
     * for example, if used in ON_INACTIVE, it will unsubscribe in ON_STOP.
     *
     * @param lifecycle the lifecycle sequence of an Ability
     * @param <T>       type of event
     * @return reusable {@link LifecycleTransformer} that unsubscribes the source during the Ability lifecycle
     */
    @NonNull
    @CheckResult
    public static <T> LifecycleTransformer<T> bindLifecycle(@NonNull Observable<Lifecycle.Event> lifecycle) {
        return bind(lifecycle, LIFECYCLE);
    }
}
